using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using UnityEditor;
using UnityEngine;

public class LuaBuilder : BuildScript
{
    public override string fileExtensions
    {
        get { return ".lua,.txt,.bytes"; }
    }

    public bool forceUpdate = false;

    [MenuItem("Tools/Lua/BuildLuaVersion")]
    public static void BuildLuaVersion()
    {
        LuaBuilder luaBuilder = new LuaBuilder();

        luaBuilder.StartBuild(Path.Combine(Application.dataPath, GameUtility.EditorLuaPath));
        //System.Version
    }
    
    [MenuItem("Tools/Lua/CopyLuaVersion")]
    public static void CopyLuaVersion()
    {
        GameUtility.CopyDire2Target(Path.Combine(Application.dataPath, GameUtility.EditorLuaPath),$"{Application.streamingAssetsPath}/Res/Lua");
        AssetDatabase.Refresh();
        //System.Version
    }
    // CopyDire2Target
    [MenuItem("Tools/Lua/BuildForceLuaVersion")]
    public static void BuildForceLuaVersion()
    {
        LuaBuilder luaBuilder = new LuaBuilder()
        {
            forceUpdate = true
        };

        luaBuilder.StartBuild(Path.Combine(Application.dataPath, GameUtility.EditorLuaPath));
        //System.Version
    }

    public List<LuaFile> FileInfos = new List<LuaFile>();

    protected override void CollectAssetBuild()
    {
        base.CollectAssetBuild();
        DirectoryInfo rootPath = new DirectoryInfo(this.buildPath);
        if (!rootPath.Exists)
        {
            Debug.LogError($"path : {rootPath.FullName} is not found !!!!!");
            return;
        }

        Queue<DirectoryInfo> foreachPath = new Queue<DirectoryInfo>();
        foreachPath.Enqueue(rootPath);
        do
        {
            var curDirectory = foreachPath.Dequeue();
            var allFiles = curDirectory.GetFiles("*");
            if (allFiles.Length > 0)
            {
                List<FileInfo> fileList = new List<FileInfo>();

                foreach (var fileInfo in allFiles)
                {
                    var localPath = GameUtility.GetRelativePath(fileInfo.FullName, rootPath.FullName);
                    if (GameUtility.CheckExtensions(fileInfo.Extension, fileExtensions))
                    {
                        using (var stream = fileInfo.Open(FileMode.Open, FileAccess.Read))
                        {
                            string md5Code = MD5Utils.GetMD5(stream);
                            var file = new LuaFile()
                            {
                                filePath = fileInfo.FullName,
                                assetPath = localPath,
                                hashCode = fileInfo.GetHashCode(),
                                length = fileInfo.Length,
                                MD5 = md5Code,
                            };
                            FileInfos.Add(file);
                        }

                        // fileList.Add(fileInfo);
                    }
                }
            }

            var childDirectories = curDirectory.GetDirectories();
            foreach (var child in childDirectories)
            {
                foreachPath.Enqueue(child);
            }
        } while (foreachPath.Count != 0);

        Debug.LogError(GetAllAssetSize());
    }

    protected override void GenVersion()
    {
        base.GenVersion();
        FileInfo versionFile = new FileInfo(Path.Combine(buildPath, GameUtility.OutPutLuaVersionFile));
        VersionCode oldCode = null;
        DirectoryInfo rootPath = new DirectoryInfo(this.buildPath);
        if (versionFile.Exists)
        {
            var jsonCode = File.ReadAllText(versionFile.FullName);
            oldCode = JsonUtility.FromJson<VersionCode>(jsonCode);
        }

        VersionCode code = new VersionCode();
        code.largeCode = Application.productName;
        code.lowCode = Application.unityVersion;
        code.resCode = rootPath.GetHashCode().ToString();

        code.files = FileInfos;
        List<string> changeFiles = new List<string>();
        List<string> delFiles = new List<string>();
        List<string> addFiles = new List<string>();
        if (oldCode != null)
        {
            /// 检查有没有文件被删除
            foreach (var file in oldCode.files)
            {
                var contains = code.files.Find(f => { return f.assetPath == file.assetPath; });
                if (contains == null)
                {
                    delFiles.Add(contains.assetPath);
                }
            }


            foreach (var file in code.files)
            {
                var contains = oldCode.files.Find(f => { return f.assetPath == file.assetPath; });
                if (contains == null)
                {
                    addFiles.Add(contains.assetPath);
                }
                else
                {
                    if (contains.MD5 != file.MD5)
                    {
                        changeFiles.Add(contains.assetPath);
                    }
                }
                // oldCode.files.Contains;
            }

            code.addFilePath = addFiles;
            code.delFilePath = delFiles;
            code.updateFilePath = changeFiles;
        }

        bool needUpdate = false;
        if (oldCode == null || forceUpdate || (addFiles.Count > 0 || delFiles.Count > 0 || changeFiles.Count > 0))
        {
            needUpdate = true;
        }
        else
        {
            Debug.LogError("不需要更新");
            return;
        }

        if (changeFiles.Count > 0)
        {
            Debug.LogError($"change files : {changeFiles.Count} {DebugFiles(changeFiles)}");
        }
        
        if (delFiles.Count > 0)
        {
            Debug.LogError($"delFiles files : {delFiles.Count} {DebugFiles(delFiles)}");
        }
        
        if (addFiles.Count > 0)
        {
            Debug.LogError($"addFiles files : {addFiles.Count} {DebugFiles(addFiles)}");
        }
        
        var newJsonCode = JsonUtility.ToJson(code, true);
        File.WriteAllText(versionFile.FullName, newJsonCode);
        Debug.LogError($"写入新的版本 {newJsonCode}");
    }

    // void Ex

    long GetAllAssetSize()
    {
        long size = 0;
        foreach (var fileInfo in FileInfos)
        {
            size += fileInfo.length;
        }

        return size;
    }

    string DebugFiles(List<string> files)
    {
        StringBuilder builder = new StringBuilder();
        foreach (var VARIABLE in files)
        {
            builder.AppendLine(VARIABLE);
        }

        return builder.ToString();
    }
}